#include "his_stream.h"
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
# if __BYTE_ORDER == __BIG_ENDIAN
# define ntohll(x)      (x)
# define htonll(x)      (x)
# else
#  if __BYTE_ORDER == __LITTLE_ENDIAN
#   define ntohll(x)    __bswap_64 (x)
#   define htonll(x)    __bswap_64 (x)
#  endif
# endif


#endif

CHisStream::CHisStream(unsigned int nGrowBytes/*=1024*/)
	: m_stream(nGrowBytes)
{
}

CHisStream::CHisStream(void* pBuffer, unsigned int bufferSize)
	: m_stream(pBuffer, bufferSize)
{
}

void CHisStream::Attach(void* pBuffer, unsigned int bufferSize)
{
	m_stream.Attach(pBuffer, bufferSize);
}

void* CHisStream::Detach()
{
	return m_stream.Detach();
}

CHisStream::~CHisStream()
{
}

unsigned int CHisStream::GetSize() const
{
	return m_stream.GetSize();
}

void CHisStream::SetSize(unsigned int newSize)
{
	m_stream.SetSize(newSize);
}

unsigned int CHisStream::Read(void* pBuffer, unsigned int size)
{
	return m_stream.Read(pBuffer, size);
}

unsigned int CHisStream::Pick(void* pBuffer, unsigned int size)
{
	return m_stream.Pick(pBuffer, size);
}

unsigned int CHisStream::Write(const void* pBuffer, unsigned int size)
{
	return m_stream.Write(pBuffer, size);
}

unsigned int CHisStream::Seek(int offset, int whence)
{
	return m_stream.Seek(offset, whence);
}

void CHisStream::Flush()
{
	m_stream.Flush();
}

void CHisStream::Close()
{
	m_stream.Close();
}

void CHisStream::Abort()
{
	m_stream.Abort();
}

bool CHisStream::ReadInt8(int8_t* pDst)
{
	return m_stream.ReadInt8(pDst);
}

bool CHisStream::ReadUint8(uint8_t* pDst)
{
	return m_stream.ReadUint8(pDst);
}

bool CHisStream::ReadInt16(int16_t* pDst)
{
	if (!m_stream.ReadInt16(pDst))
		return false;
	*pDst = (int16_t)ntohs((uint16_t)*pDst);
	return true;
}

bool CHisStream::ReadUint16(uint16_t* pDst)
{
	if (!m_stream.ReadUint16(pDst))
		return false;
	*pDst = ntohs(*pDst);
	return true;
}

bool CHisStream::ReadInt32(int32_t* pDst)
{
	if (!m_stream.ReadInt32(pDst))
		return false;
	*pDst = (int32_t)ntohl((uint32_t)*pDst);
	return true;
}

bool CHisStream::ReadUint32(uint32_t* pDst)
{
	if (!m_stream.ReadUint32(pDst))
		return false;
	*pDst = ntohl(*pDst);
	return true;
}

bool CHisStream::ReadInt64(int64_t* pDst)
{
	if (!m_stream.ReadInt64(pDst))
		return false;
	*pDst = (int64_t)ntohll((uint64_t)*pDst);
	return true;
}

bool CHisStream::ReadUint64(uint64_t* pDst)
{
	if (!m_stream.ReadUint64(pDst))
		return false;
	*pDst = ntohll(*pDst);
	return true;
}

bool CHisStream::ReadSingle(float* pDst)
{
	unsigned int nread = m_stream.Read(pDst, sizeof(float));
	return (nread == sizeof(float));
}

bool CHisStream::ReadDouble(double* pDst)
{
	unsigned int nread = m_stream.Read(pDst, sizeof(double));
	return (nread == sizeof(double));
}

bool CHisStream::ReadSmallString(char* psz, int len)
{
	uint8_t slen = 0;
	if (!ReadUint8(&slen))
		return false;
	if (slen >= len)
		return false;
	unsigned int size = slen * sizeof(char);
	unsigned int nread = Read(psz, size);
	if (nread != size)
		return false;
	psz[slen] = 0;
	return true;
}

bool CHisStream::ReadShortString(char* psz, int len)
{
	uint16_t slen = 0;
	if (!ReadUint16(&slen))
		return false;
	if (slen >= len)
		return false;
	unsigned int size = slen * sizeof(char);
	unsigned int nread = Read(psz, size);
	if (nread != size)
		return false;
	psz[slen] = 0;
	return true;
}

bool CHisStream::ReadString(char* psz, int len)
{
    if (len < 0)
        return false;
	uint32_t slen = 0;
	if (!ReadUint32(&slen))
		return false;
	if (slen >= (uint32_t)len)
		return false;
	unsigned int size = slen * sizeof(char);
	unsigned int nread = Read(psz, size);
	if (nread != size)
		return false;
	psz[slen] = 0;
	return true;
}
// 
// bool CHisStream::ReadSmallCString(CString& str)
// {
// 	uint8_t slen = 0;
// 	if (!ReadUint8(&slen))
// 		return false;
// 	char* psz = str.GetBuffer(slen);
// 	unsigned int size = slen * sizeof(char);
// 	unsigned int nread = Read(psz, size);
// 	if (nread != size)
// 	{
// 		str.ReleaseBuffer(0);
// 		return false;
// 	}
// 	else
// 	{
// 		str.ReleaseBuffer(slen);
// 		return true;
// 	}
// }
// 
// bool CHisStream::ReadShortCString(CString& str)
// {
// 	uint16_t slen = 0;
// 	if (!ReadUint16(&slen))
// 		return false;
// 	char* psz = str.GetBuffer(slen);
// 	unsigned int size = slen * sizeof(char);
// 	unsigned int nread = Read(psz, size);
// 	if (nread != size)
// 	{
// 		str.ReleaseBuffer(0);
// 		return false;
// 	}
// 	else
// 	{
// 		str.ReleaseBuffer(slen);
// 		return true;
// 	}
// }
// 
// bool CHisStream::ReadCString(CString& str)
// {
// 	uint32_t slen = 0;
// 	if (!ReadUint32(&slen))
// 		return false;
// 	char* psz = str.GetBuffer(slen);
// 	unsigned int size = slen * sizeof(char);
// 	unsigned int nread = Read(psz, size);
// 	if (nread != size)
// 	{
// 		str.ReleaseBuffer(0);
// 		return false;
// 	}
// 	else
// 	{
// 		str.ReleaseBuffer(slen);
// 		return true;
// 	}
// }

bool CHisStream::WriteInt8(int8_t src)
{
	unsigned int nwrite = Write(&src, sizeof(int8_t));
	return (nwrite == sizeof(int8_t));
}

bool CHisStream::WriteUint8(uint8_t src)
{
	unsigned int nwrite = Write(&src, sizeof(uint8_t));
	return (nwrite == sizeof(uint8_t));
}

bool CHisStream::WriteInt16(int16_t src)
{
	src = (int16_t)htons((uint16_t)src);
	unsigned int nwrite = Write(&src, sizeof(int16_t));
	return (nwrite == sizeof(int16_t));
}

bool CHisStream::WriteUint16(uint16_t src)
{
	src = htons(src);
	unsigned int nwrite = Write(&src, sizeof(uint16_t));
	return (nwrite == sizeof(uint16_t));
}

bool CHisStream::WriteInt32(int32_t src)
{
	src = (int32_t)htonl((uint32_t)src);
	unsigned int nwrite = Write(&src, sizeof(int32_t));
	return (nwrite == sizeof(int32_t));
}

bool CHisStream::WriteUint32(uint32_t src)
{
	src = htonl(src);
	unsigned int nwrite = Write(&src, sizeof(uint32_t));
	return (nwrite == sizeof(uint32_t));
}

bool CHisStream::WriteInt64(int64_t src)
{
	src = (int64_t)htonll((uint64_t)src);
	unsigned int nwrite = Write(&src, sizeof(int64_t));
	return (nwrite == sizeof(int64_t));
}

bool CHisStream::WriteUint64(uint64_t src)
{
	src = htonll(src);
	unsigned int nwrite = Write(&src, sizeof(uint64_t));
	return (nwrite == sizeof(uint64_t));
}

bool CHisStream::WriteSingle(float src)
{
	unsigned int nwrite = Write(&src, sizeof(float));
	return (nwrite == sizeof(float));
}

bool CHisStream::WriteDouble(double src)
{
	unsigned int nwrite = Write(&src, sizeof(double));
	return (nwrite == sizeof(double));
}

bool CHisStream::WriteSmallString(const char* psz, int len/*=-1*/)
{
	if (len < 0)
		len = strlen(psz);
	if (len > 0xff)
		return false;
	if (!WriteUint8((uint8_t)len))
		return false;
	unsigned int size = len * sizeof(char);
	if (Write(psz, size) != size)
		return false;
	return true;
}

bool CHisStream::WriteShortString(const char* psz, int len/*=-1*/)
{
	if (len < 0)
		len = strlen(psz);
	if (len > 0xffff)
		return false;
	if (!WriteUint16((uint16_t)len))
		return false;
	unsigned int size = len * sizeof(char);
	if (Write(psz, size) != size)
		return false;
	return true;
}

bool CHisStream::WriteString(const char* psz, int len/*=-1*/)
{
	if (len < 0)
		len = strlen(psz);
	if (!WriteUint32((uint32_t)len))
		return false;
	unsigned int size = len * sizeof(char);
	if (Write(psz, size) != size)
		return false;
	return true;
}

// bool CHisStream::WriteSmallCString(const CString& str)
// {
// 	if (str.GetLength() > 0xff)
// 		return false;
// 	if (!WriteUint8((uint8_t)str.GetLength()))
// 		return false;
// 	unsigned int size = str.GetLength() * sizeof(char);
// 	if (Write(str.c_str(), size) != size)
// 		return false;
// 	return true;
// }
// 
// bool CHisStream::WriteShortCString(const CString& str)
// {
// 	if (str.GetLength() > 0xffff)
// 		return false;
// 	if (!WriteUint16((uint16_t)str.GetLength()))
// 		return false;
// 	unsigned int size = str.GetLength() * sizeof(char);
// 	if (Write(str.c_str(), size) != size)
// 		return false;
// 	return true;
// }
// 
// bool CHisStream::WriteCString(const CString& str)
// {
// 	if (!WriteUint32((uint32_t)str.GetLength()))
// 		return false;
// 	unsigned int size = str.GetLength() * sizeof(char);
// 	if (Write(str.c_str(), size) != size)
// 		return false;
// 	return true;
// }
